home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / d3d.zip / SPH80.C < prev    next >
Text File  |  1989-11-22  |  4KB  |  160 lines

  1. /* SPH80: Polyhedron with 80 triangular faces to approximate a sphere.
  2.    It is based on an icosahedron, which is a regular polyhedron with
  3.    20 equilateral triangles, four smaller traingles are used, which gives
  4.    20 x 4 = 90 of these smaller triangles (not equilateral).  For each
  5.    equilateral triangle of the icosahedron, the midpoints of its three
  6.    sides are projected onto the sphere in which the icosahedron fits.
  7.    We obtain the four smaller triangles by connecting the neighboring
  8.    points. */
  9.  
  10. #include <stdio.h>
  11. #include <math.h>
  12. #include <process.h>
  13.  
  14. void point(int i, float x, float y, float z);
  15. void subdivide(int A, int B, int C);
  16. void storeface(int i, int j, int k);
  17. void midpnt(int B, int C, int *pP, float x, float y, float z);
  18.  
  19. int npoints;
  20. struct {float x, y, z;} pnt[43];
  21.  
  22. int nface=0;
  23. struct {int i, j, k;} fc[80];
  24.  
  25. int nedge=0;
  26. struct {i, j, P;} edges[120];
  27.  
  28. FILE *fp;
  29.  
  30. main()
  31. {
  32.    int i, l;
  33.    double pi, r, alpha, tau;
  34.  
  35.    pi = 4.0 * atan(1.0);
  36.    tau = (sqrt(5.0) + 1)/2;      /* tau = 2 * cos(pi/5.0)   */
  37.    r = tau - 0.5;
  38.  
  39.    printf("A sphere (with radius 1) is approximated\n");
  40.     printf("by an object with 80 triangular bounding\n");
  41.    printf("faces. The results are written to the \n");
  42.    printf("object file SPH80.DAT (which is read by D3D.\n");
  43.  
  44.    fp = fopen("SPH80.DAT","w");
  45.    point(1, 0.0, 0.0, 1.0);      /* North Pole */
  46.    for(i=0; i<5; i++) {
  47.       alpha = -pi/5 + i*pi/2.5;  /* degrees: -36 + i*72 */
  48.         point(2+i, cos(alpha)/r, sin(alpha)/r, 0.5/r);
  49.    }
  50.    for(i=0; i<5; i++) {
  51.       alpha = i * pi/2.5;
  52.         point(7+i, cos(alpha)/r, sin(alpha)/r, -0.5/r);
  53.    }
  54.    point(12, 0.0, 0.0, -1.0);    /* South Pole */
  55.    npoints = 12;
  56.    for(i=0; i<5; i++) subdivide(1, 2+i, i<4 ? 3+i : 2);
  57.     for(i=0; i<5; i++) subdivide(2+i, 7+i, i<4 ? 3+i : 2);
  58.    for(i=0; i<5; i++) subdivide(7+i, i<4 ? 8+i : 7, i<4 ? 3+i : 2);
  59.    for(i=0; i<5; i++) subdivide(7+i, 12, i<4 ? 8+i : 7);
  60.  
  61.    fprintf(fp, "Faces:\n");
  62.    for(l=0; l<80; l++)
  63.       fprintf(fp, "%d %d %d.\n", fc[l].i, fc[l].j, fc[l].k);
  64.    fclose(fp);
  65. }
  66.  
  67. void midpnt(int B, int C, int *pP, float x, float y, float z)
  68. /* Point(x, y, z) is the midpoint of BC.  If it is a new vertex,
  69.    store it and write it to the object file, using a new vertex
  70.    number.  If not, find its vertex number.  The vertex number
  71.    is to be assigned to *pP anyway.
  72. */
  73. {
  74.    int tmp, e;
  75.    if(C < B) {
  76.       tmp = B;
  77.       B = C;
  78.       C = tmp;
  79.    }
  80.    /* B, C in increasing order, for the sake of uniqueness */
  81.  
  82.    for(e=0; e<nedge; e++)
  83.         if(edges[e].i == B && edges[e].j == C)
  84.          break;
  85.    if(e == nedge) {  /* Not found, so we have a new vertex */
  86.       edges[e].i = B;
  87.       edges[e].j = C;
  88.       edges[e].P = *pP = ++npoints;
  89.       nedge++;
  90.       point(*pP, x, y, z);
  91.    }
  92.     else
  93.       *pP = edges[e].P;
  94.  
  95.      /* Edge BD has been dealt with before,
  96.         so the vertex is not new.  */
  97. }
  98.  
  99. void point(int i, float x, float y, float z)
  100. {
  101.    fprintf(fp, "%d %f %f %f\n", i, x, y, z);
  102.    pnt[i].x = x;
  103.    pnt[i].y = y;
  104.    pnt[i].z = z;
  105. }
  106.  
  107. void subdivide(int A, int B, int C)
  108. /* Divide triangle ABC into four samller triangles */
  109. {
  110.    float xP, xQ, xR,
  111.          yP, yQ, yR,
  112.          zP, zQ, zR;
  113.    int    P,  Q,  R;
  114.  
  115.    static float d = -1;
  116.  
  117.    /* d is equal to -1 only before the first call of this function;
  118.       after this, d will have its correct value (between 0 and 1),
  119.       namely the distance between any midpoint and the center of the
  120.       sphere.  We project all midpoints onto the sphere (with radius
  121.       1) by dividing their coordinates by d.
  122.    */
  123.  
  124.    xP = (pnt[B].x + pnt[C].x)/2;
  125.    yP = (pnt[B].y + pnt[C].y)/2;
  126.     zP = (pnt[B].z + pnt[C].z)/2;
  127.  
  128.    xQ = (pnt[C].x + pnt[A].x)/2;
  129.    yQ = (pnt[C].y + pnt[A].y)/2;
  130.    zQ = (pnt[C].z + pnt[A].z)/2;
  131.  
  132.    xR = (pnt[A].x + pnt[B].x)/2;
  133.    yR = (pnt[A].y + pnt[B].y)/2;
  134.    zR = (pnt[A].z + pnt[B].z)/2;
  135.  
  136.    if (d < 0)
  137.       d = sqrt(xP*xP + yP*yP + zP*zP);    /* 0 < d < 1 */
  138.          
  139.    xP /= d; xQ /= d; xR /= d; 
  140.    yP /= d; yQ /= d; yR /= d;
  141.    zP /= d; zQ /= d; zR /= d;
  142.  
  143.    midpnt(B, C, &P, xP, yP, zP);
  144.    midpnt(C, A, &Q, xQ, yQ, zQ);
  145.    midpnt(A, B, &R, xR, yR, zR);
  146.  
  147.    storeface(A, R, Q);
  148.    storeface(R, B, P);
  149.    storeface(Q, P, C);
  150.    storeface(Q, R, P);
  151. }
  152.  
  153. void storeface(int i, int j, int k)
  154. {
  155.    fc[nface].i = i;
  156.    fc[nface].j = j;
  157.    fc[nface].k = k;
  158.    nface++;
  159. }
  160.